package com.teacher.hong.controller;

import com.teacher.hong.exception.ServiceValidationException;
import com.teacher.hong.utils.TokenUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import java.io.*;
import java.util.Date;

/**
 * 文件相关控制器
 */
@Slf4j
@RestController
@RequestMapping("file")
public class FileController extends BaseController {

    /**
     * 文件上传
     * @param partFile
     * @return
     * @throws IOException
     */
    @PostMapping("upload")
    public Object upload(@ModelAttribute MultipartFile partFile) throws IOException {
        //获取图片名称
//        String fileName = partFile.getOriginalFilename();   //获取原始文件名
        /*
        partFile.getOriginalFilename() ==>  baiqian.jpg
         */
        String fileName = new Date().getTime() + partFile.getOriginalFilename().substring(partFile.getOriginalFilename().indexOf("."));
        //设置文件保存的路径
        String uploadPath = request.getServletContext().getInitParameter("uploadPath");
        File fileFolderPath = new File(uploadPath);
        if (!fileFolderPath.exists()) fileFolderPath.mkdirs();  //如果上传路径不存在，则创建上传路径
        log.info("uploadPath:" + uploadPath);
        //创建一个保存文件
        File storeFile = new File(fileFolderPath + "/" + fileName);
        partFile.transferTo(storeFile); //保存文件到指定File对象，并写到磁盘上
        return success(null,"/upload/" + fileName);
    }

    /**
     * 文件列表
     * @return
     */
    @GetMapping("list")
    public Object list() {
        String uploadPath = request.getServletContext().getInitParameter("uploadPath");
        File fileFolderPath = new File(uploadPath);
        String[] files = fileFolderPath.list();
        return success(null, files);
    }

    /**
     * 文件下载
     * @param fileName
     * @throws IOException
     */
    @GetMapping("download/{token}/{fileName}")
    public void download(@PathVariable String token, @PathVariable String fileName) throws IOException {
        /*
            在这儿进行权限控制
            如果权限通过，则继续执行后面的代码，如果权限不足，则抛出一个异常，阻止后续代码执行，
            达到阻止下载的目的。
            如果进行权限控制呢？
            1. 我们给学生下载的。
            2. 不允许匿名下载，增加token认证
            3. 根据token获取当前学生的余额，每次下次扣除20元，如果余额不足，则不允许下载。
         */

        String account = TokenUtils.verify(token);  //获取当前下载者的学生账号
        if (account == null) {
            throw new ServiceValidationException("权限不足，请先登录。", 401);
        }
        log.info(account + "进入下载，文件：" + fileName);


        //请求响应头
        response.setHeader("Content-Type", "application/x-msdownload");
        response.setHeader("Content-Disposition", "attachment;filename=" + toUTF8String(fileName));
        //设置文件保存的路径
        String uploadPath = request.getServletContext().getInitParameter("uploadPath");
        File file = new File(uploadPath + "/" + fileName);  //获取要下载的文件对象
        if (!file.exists()) {
            throw new ServiceValidationException("文件不存在", 402);
        }
        //输入流
        FileInputStream inputStream = new FileInputStream(file);
        //输出流
        ServletOutputStream outputStream = response.getOutputStream();
        outputStream.flush();
        int read = 0;   //读取次数
        byte[] bytes = new byte[inputStream.available()];
        while (inputStream != null && (read = inputStream.read(bytes)) != -1) {
            outputStream.write(bytes, 0, read);
        }
        //把文件流输出
        outputStream.flush();
        //关闭流
        inputStream.close();
        outputStream.close();
    }


    /**
     * 下载文件的文件名的字符编码转换
     * @param str
     * @return
     */
    private String toUTF8String(String str) {
        StringBuffer stringBuffer = new StringBuffer();
        int length = str.length();
        for (int i = 0; i< length; i++) {
            //取出字符串中的每个字符
            char c = str.charAt(i);
            //Unicode码值为0~255时，不做处理
            if (c >= 0 && c <= 255) {
                stringBuffer.append(c);
            } else {
                //进行UTF-8转码
                byte b[];
                try{
                    b = Character.toString(c).getBytes("UTF-8");
                } catch (UnsupportedEncodingException exception) {
                    exception.printStackTrace();
                    b = null;
                }
                //转换为%HH的字符串形式
                for (int j = 0; j < b.length; j++) {
                    int k = b[j];
                    if (k < 0) {
                        k &= 255;
                    }
                    stringBuffer.append("%" + Integer.toHexString(k).toUpperCase());
                }
            }
        }
        return stringBuffer.toString();
    }


}
